/*
 * FanTempCtrl13.c
 *
 * Created: 08-01-2014 00:06:44
 *  Author: Karmu
 */ 

#define F_CPU 1200000UL
#include <avr/io.h>
#include <util/delay.h>

#define PORT	PORTB
#define DDR		DDRB
#define	PWM		0
#define TMP		3

void adc_init(void);
uint16_t adc_read(uint8_t ch);
uint16_t adc_avg(uint8_t ch);

int main(void)
{
	uint16_t temperature;
	adc_init();
	
	/* setup input/outputs */
	DDR |= _BV(PWM);
	DDR &= ~_BV(TMP);
	
	/* setup phase corrected PWM for motor*/
	/* Set OC0A on Compare Match when up-counting.
	Clear OC0A on Compare Match when down-counting. */
	TCCR0A |= _BV(COM0A1) | _BV(WGM00);
	/* Phase Correct and Phase and Frequency Correct PWM (mode 1)*/
	//TCCR0A |= _BV(WGM00);
	//clkI/O/64 (From prescaler) 34.7Hz
	TCCR0B |= _BV(CS01) | _BV(CS00);
	
	while(1){
		temperature=adc_avg(TMP);
		
		if (temperature<25) OCR0A=0; //0%
		else if (temperature>=25 && temperature<40) OCR0A=64; //25%
		else if (temperature>=40 && temperature<60) OCR0A=128; //50%
		else if (temperature>=60 && temperature<75) OCR0A=191; //75%
		else if (temperature>=75) OCR0A=255; //100%
		else OCR0A = 0;
	}	
}
void adc_init(void)
{
	// initialize adc
	// AREF = 1.1V (Internal Voltage reference)
	//ADMUX = (1<<REFS0);
	
	// ADC Enable and prescaler of 16 to get a ADC clock between 50kHz to 200kHz
	// 1200000/16 = 75000
	ADCSRA = (1<<ADEN)|(1<<ADPS2);
}

uint16_t adc_read(uint8_t ch)
{
	// read adc value
	// select the corresponding channel 0~3
	// ANDing with '3' will always keep the value
	// of 'ch' between 0 and 3
	ch &= 0b00000011;  // AND operation with3
	ADMUX = (ADMUX & 0xFC)|ch;     // clears the bottom 2 bits before ORing
	
	// start single conversion
	// write '1' to ADSC
	ADCSRA |= (1<<ADSC);
	
	// wait for conversion to complete
	// ADSC becomes '0' again
	// till then, run loop continuously
	while(ADCSRA & (1<<ADSC));
	
	return (ADC);
}

uint16_t adc_avg(uint8_t ch)
{
	uint8_t sample=0;
	uint16_t adc=0;
	for(sample=0;sample<64;sample++)
	{
		adc+=(adc_read(ch));
		_delay_us(20); 
	} 
	adc=adc>>7; //division by 32
	return adc;
}
